﻿using System;
using System.Collections.Generic;
using netDxf;
using netDxf.Entities;
using netDxf.Tables;

namespace TestDxfDocument
{
    class Pus
    {
        /// <summary>
        /// 返回相交直线与圆的过渡圆弧的圆心
        /// </summary>
        /// <param name="objCir"></param>
        /// <param name="p1"></param>
        /// <param name="p2"></param>
        /// <param name="radius"></param>
        /// <returns></returns>
        /// <exception cref="NullReferenceException"></exception>
        /// <exception cref="Exception"></exception>
        public static Vector2 GetTangentCircleCenter(Circle objCir, Vector2 p1, Vector2 p2, double radius)
        {
            if (objCir == null)
            {
                throw new NullReferenceException("objCir 引用为空");
            }

            if (p1.Equals(p2))
            {
                throw new Exception("参数p1,p2是同一点");
            }
            
            if (radius <= 0)
            {
                throw new Exception("相切的过渡圆弧的半径应当为正");
            }

            var xpoints = LineXCir(objCir, p1, p2);
            if (xpoints == null)
            {
                throw new Exception("直线与圆并未相交,无法生成过渡圆弧");
            }
            
            //线性变换旋转角度
            var alpha = Vector2.Angle(p1 , p2);
            alpha %= pi;
            alpha = pi / 2 - alpha;
            //旋转矩阵
            var rm2 = Matrix2.Rotation(alpha);
            //旋转
            var rCen = rm2 * ToV2(objCir.Center);
            var rp1 = rm2 * p1;
//            var rp2 = rm2 * p2;
            //旋转后rp1与rp2的x坐标应该相等
            var xr = Math.Asin((rp1.X - rCen.X - radius) / (objCir.Radius - radius));
            //相切圆弧的圆心位置，可能有两个，目前取离-pi/2较近的那个
            var tCen = Vector2.Polar(rCen, objCir.Radius - radius, -pi / 2 + xr);
            //乘以逆矩阵，得到在初始坐标中的位置
            var cen = rm2.Inverse() * tCen;
            return cen;
        }

        /// <summary>
        /// 平移多段线
        /// </summary>
        /// <param name="lwPolyline"></param>
        /// <param name="offset"></param>
        /// <returns></returns>
        /// <exception cref="NullReferenceException"></exception>
        public static LwPolyline OffsetLwPolyline(LwPolyline lwPolyline, Vector2 offset)
        {
            if (lwPolyline == null)
            {
                throw new NullReferenceException("多段线引用为空");
            }
            
            var after = lwPolyline.Clone() as LwPolyline;
            var vetexes = after.Vertexes;
            foreach (var vertex in vetexes)
            {
                vertex.Position += offset;
            }
            return after;
        }

        /// <summary>
        /// 返回圆弧的中心线角度Degree，角度指圆心到圆弧上选定点所定义的向量的角度
        /// </summary>
        /// <param name="arc"></param>
        /// <returns></returns>
        /// <exception cref="NullReferenceException"></exception>
        public static double GetArcCenterLineAglD(Arc arc)
        {
            if (arc == null)
            {
                throw new NullReferenceException("圆弧对象引用为空");
            }

            return (arc.StartAngle + arc.EndAngle) / 2;
        }

        /// <summary>
        /// 通过圆弧的中心点，起点，终点，返回其凸度
        /// 起点-终点是逆时针方向
        /// </summary>
        /// <param name="center"></param>
        /// <param name="startPoint"></param>
        /// <param name="endPoint"></param>
        /// <returns></returns>
        public static double GetArcBulge(Vector2 center,Vector2 startPoint,Vector2 endPoint)
        {
            var sa = Vector2.Angle(center, startPoint);
            var ea = Vector2.Angle(center, endPoint);
            var arcAgl = ea - sa;
            if (arcAgl < 0)
            {
                arcAgl = ea + MathHelper.TwoPI - sa;
            }

            var qua = arcAgl / 4;
            return Math.Tan(qua);
        }

        /// <summary>
        /// 返回 a*sinx + b*cosx = c的x
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <param name="c"></param>
        /// <returns></returns>
        public static double GetFormatAlpha(double a, double b, double c)
        {
            var alpha = Math.Asin(b / Math.Sqrt(a * a + b * b));
            var theAgl = Math.Asin(c / Math.Sqrt(a * a + b * b)) - alpha;
            if (Double.IsNaN(theAgl))
            {
                throw new Exception("浮点非数字值");
            }
            return Math.Abs( theAgl);
        }

        /// <summary>
        /// 翻转，即x轴反转
        /// </summary>
        /// <param name="lwPolyline"></param>
        /// <returns></returns>
        public static LwPolyline XaxisReverse(LwPolyline lwPolyline)
        {
            var vetexes = lwPolyline.Vertexes;
            var afterReverse = new LwPolyline();
            var reverseM = new Matrix2( -1,0,0,1);
            foreach (var vertex in vetexes)
            {
                afterReverse.Vertexes.Add(new LwPolylineVertex(reverseM * vertex.Position,-vertex.Bulge));
            }

            afterReverse.Layer = lwPolyline.Layer;
            return afterReverse;
        }

//        public static LwPolyline Fillet4LwPline(LwPolyline lwPolyline, Dictionary<int, double> obj)
//        {
//            var indexKeys = obj.Keys;
//        }

        /// <summary>
        /// 将多段线的第index个点变为相切圆弧（相当于倒圆角fillet），返回的是新的对象，不是在原对象上做修改
        /// </summary>
        /// <param name="lwPolyline"></param>
        /// <param name="index"></param>
        /// <param name="radius"></param>
        /// <param name="antiClockWise"></param>
        /// <returns></returns>
        public static LwPolyline Fillet4LwPline(LwPolyline lwPolyline, int index, double radius)//倒圆角
        {
            var vertexes = lwPolyline.Vertexes;
            if (!lwPolyline.IsClosed && index == 0)
            {
                throw new Exception("不能将非封闭多段线的第一点用来倒圆角");
            }
            if (!lwPolyline.IsClosed && index == vertexes.Count)
            {
                throw new Exception("不能将非封闭多段线的最后一个点用来倒圆角");
            }

            var afterLine = new LwPolyline();
            var counter = 0;
            for (var i = 0; i < vertexes.Count; i++)
            {
                if (index == i)
                {
                    var v1 = vertexes[i - 1].Position;
                    var v2 = vertexes[i].Position;
                    var v3 = vertexes[i + 1].Position;
                    var angleR = SmallAngle(v1, v2, v3);
                    // Console.WriteLine(angleR * 180 / pi);
                    var dis = radius / Math.Tan(angleR / 2);
                    var vs = Vector2.Polar(v2, dis, Vector2.Angle(v2, v1));
                    var ve = Vector2.Polar(v2, dis, Vector2.Angle(v2, v3));

                    var bulge = Math.Tan((pi - angleR) / 4);
                    var crossProduct = Vector2.CrossProduct(vs - v2, ve - v2);//！！！向量是以原点为基准的，减去v2后才是实际需要的那个向量！！！
                    // Console.WriteLine(crossProduct);
                    if (crossProduct > 0)
                    {
                        bulge = -bulge;
                    }
                    //lwpolyline要通过这种add方法添加vetex，不要用[index]= vetex 的方式赋值，会报超出索引范围的错误。
                    afterLine.Vertexes.Add(new LwPolylineVertex(vs,bulge));
                    afterLine.Vertexes.Add(new LwPolylineVertex(ve,0));
                }
                else
                {
                    afterLine.Vertexes.Add(vertexes[i]);
                }
            }

            afterLine.Layer = lwPolyline.Layer;
            return afterLine;
        }

        /// <summary>
        /// 通过二维向量的叉积判断向量another是否在向量basis的左手边,即 basis X another
        /// </summary>
        /// <param name="basis"></param>
        /// <param name="another"></param>
        /// <returns></returns>
        public static bool IsLeftHand(Vector2 basis, Vector2 another)
        {
            var crossProduct = Vector2.CrossProduct(basis, another);
            return (crossProduct > 0) ? true : false;
        }

        /// <summary>
        /// 三个点组成的角的角度（小于pi的那个）
        /// </summary>
        /// <param name="v1"></param>
        /// <param name="v2"></param>
        /// <param name="v3"></param>
        /// <returns></returns>
        public static double SmallAngle(Vector2 v1, Vector2 v2, Vector2 v3)
        {
            var v2Array = new Vector2[]{v1,v2,v3};
            var col = IsColline(v2Array);
            if (col)
            {
                throw new Exception("三点共线");
            }

            var a23 = Vector2.Angle(v2, v3);
            var a21 = Vector2.Angle(v2, v1);
            var a = (a23 > a21) ? (a23 - a21) : (a21 - a23);
            if (a > pi)
            {
                return MathHelper.TwoPI - a;
            }

            return a;
        }

        /// <summary>
        /// 根据起止点和半径和方向画弧
        /// </summary>
        /// <param name="startPoint"></param>
        /// <param name="endPoint"></param>
        /// <param name="radius"></param>
        /// <param name="antiClockWise"></param>
        /// <returns></returns>
        public static Arc TwoPointArc(Vector2 startPoint,Vector2 endPoint,double radius,bool antiClockWise)
        {
            var s2eAgl = Vector2.Angle(startPoint, endPoint);
            var dis = Vector2.Distance(startPoint, endPoint);
            var aglA = Math.Acos(dis / 2 / radius);
            Vector2 cen;
            if (antiClockWise)
            {
                cen = Vector2.Polar(startPoint, radius, s2eAgl + aglA);
                var startAgl = Vector2.Angle(cen, startPoint);
                var endAgl = Vector2.Angle(cen, endPoint);
                return new Arc(cen, radius, startAgl * 180 / pi, endAgl * 180 / pi);
            }
            else
            {
                cen = Vector2.Polar(startPoint, radius, s2eAgl - aglA);
                var startAgl = Vector2.Angle(cen, endPoint);
                var endAgl = Vector2.Angle(cen, startPoint);
                return new Arc(cen, radius, startAgl * 180 / pi, endAgl * 180 / pi);
            }
        }

        /// <summary>
        /// 缩放多段线
        /// </summary>
        /// <param name="lwPolyline"></param>
        /// <param name="sm"></param>
        /// <returns></returns>
        public static LwPolyline ScalingByMatrix2(LwPolyline lwPolyline, Matrix2 sm)
        {
            var v2s = new List<Vector2>();
            var bulges = new List<double>();
            foreach (var vertex in lwPolyline.Vertexes)
            {
               v2s.Add(new Vector2(vertex.Position.X,vertex.Position.Y));
               bulges.Add(vertex.Bulge);
            }
            
            var v2ss = new List<Vector2>();
            foreach (var v2 in v2s)
            {
                v2ss.Add(sm * v2);
            }

            var afterScaling = AddPointsToLwPolyLine(v2ss);
            afterScaling.Layer = lwPolyline.Layer;
            for (var i = 0; i < lwPolyline.Vertexes.Count; i++)
            {
                afterScaling.Vertexes[i].Bulge = bulges[i];
            }

            return afterScaling;
        }

        public static List<Vector2> RotateByOrigin(double angleR, List<Vector2> v2s)
        {
            var matrix3 = Matrix3.RotationZ(angleR);
            var v2Rs = new List<Vector2>(); 
            foreach (var vector2 in v2s)
            {
                var v3 = ToV3(vector2,0);
                v3 = matrix3 * v3;
                v2Rs.Add(ToV2(v3));
            }

            return v2Rs;
        }

        public static Line RotateByOrigin(double angleR, Line oLine)
        {
            var sp = ToV2(oLine.StartPoint);
            var ep = ToV2(oLine.EndPoint);

            var prs = RotateByPoint(Vector2.Zero, angleR,new Vector2[] {sp, ep});
            var nLine = new Line(ToV3(prs[1], 0),ToV3(prs[2], 0));
            nLine.Layer = oLine.Layer;
            
            return nLine;    
        }

        /// <summary>
        /// 将给定的lwpolyline绕原点旋转angleR弧度
        /// </summary>
        /// <param name="angleR"></param>
        /// <param name="lwPolyline"></param>
        /// <returns></returns>
        public static LwPolyline RotateByOrigin(double angleR, LwPolyline lwPolyline)
        {
            var v2s = new List<Vector2>();
            var bulges = new List<double>();
            foreach (var vertex in lwPolyline.Vertexes)
            {
                v2s.Add(new Vector2(vertex.Position.X,vertex.Position.Y));
                bulges.Add(vertex.Bulge);
            }
            var v2Rs = new List<Vector2>();
            Matrix3 matrixR = Matrix3.RotationZ(angleR);
            foreach (var v2 in v2s)
            {
                var v3 = new Vector3(v2.X, v2.Y, 0);
                var v3R = matrixR * v3;
                v2Rs.Add(new Vector2(v3R.X,v3R.Y));
            }

            var rLine = AddPointsToLwPolyLine(v2Rs);
            for (var i = 0; i < lwPolyline.Vertexes.Count; i++)
            {
                rLine.Vertexes[i].Bulge = bulges[i];
            }

            rLine.Layer = lwPolyline.Layer;

            return rLine;
        } 

        private static readonly double pi = Math.PI;
        //public static void LightFillCircle(DxfDocument dxf, Circle circle, int precision, double lineWidth, Layer layer)
        //{
        //    List<Vector2> vector2s = circle.PolygonalVertexes(precision);
        //    LightFillPline(dxf, vector2s, lineWidth, layer);

        //}
        /// <summary>
        /// 用solid填充line
        /// </summary>
        /// <param name="dxf"></param>
        /// <param name="vector2s"></param>
        /// <param name="lineWidth"></param>
        /// <param name="layer"></param>
        public static void LightFillPline(DxfDocument dxf, List<Vector2> vector2s,double lineWidth, Layer layer)
        {
            double al = 0;
            double an = 0;
            Solid rect;
            Solid tri = new Solid();
            int num = vector2s.Count;
            for (int i = 1; i < num - 1; i++)
            {
                al = Vector2.Angle(vector2s[i], vector2s[i - 1]);
                rect = new Solid(fun.Polar(vector2s[i - 1], al - pi / 2, lineWidth / 2), fun.Polar(vector2s[i - 1], al + pi / 2, lineWidth / 2),
                    fun.Polar(vector2s[i], al - pi / 2, lineWidth / 2), fun.Polar(vector2s[i], al + pi / 2, lineWidth / 2));
                rect.Layer = layer;
                dxf.AddEntity(rect);
                an = Vector2.Angle(vector2s[i], vector2s[i + 1]);
                if (al > an)
                {
                    if (al - an > pi)
                    {
                        tri = new Solid(vector2s[i], fun.Polar(vector2s[i], al - pi / 2, lineWidth / 2),
                            fun.Polar(vector2s[i], an + pi / 2, lineWidth / 2));
                    }
                    else if (al - an < pi)
                    {
                        tri = new Solid(vector2s[i], fun.Polar(vector2s[i], al + pi / 2, lineWidth / 2),
                            fun.Polar(vector2s[i], an - pi / 2, lineWidth / 2));
                    }
                }
                else if (an > al)
                {
                    if (an - al > pi)
                    {
                        tri = new Solid(vector2s[i], fun.Polar(vector2s[i], al + pi / 2, lineWidth / 2),
                            fun.Polar(vector2s[i], an - pi / 2, lineWidth / 2));
                    }
                    else if (an - al < pi)
                    {
                        tri = new Solid(vector2s[i], fun.Polar(vector2s[i], al - pi / 2, lineWidth / 2),
                           fun.Polar(vector2s[i], an + pi / 2, lineWidth / 2));
                    }
                }
                tri.Layer = layer;
                dxf.AddEntity(tri);
            }
            rect = new Solid(fun.Polar(vector2s[num - 2], al - pi / 2, lineWidth / 2), fun.Polar(vector2s[num - 2], al + pi / 2, lineWidth / 2),
                fun.Polar(vector2s[num - 1], al - pi / 2, lineWidth / 2), fun.Polar(vector2s[num - 1], al + pi / 2, lineWidth / 2));
            rect.Layer = layer;
            dxf.AddEntity(rect);
            
        }
        public static void LightFillPline(DxfDocument dxf, LwPolyline lwPolyline, double lineWidth, Layer layer)
        {
            List<LwPolylineVertex> lwPolylineVertices = lwPolyline.Vertexes;
            List<Vector2> vector2s = new List<Vector2>();
            for (int i = 0; i < lwPolylineVertices.Count; i++)
            {
                vector2s.Add(lwPolylineVertices[i].Position);
            }

            if (lwPolyline.IsClosed)
            {

                Vector2[] innerV2s = OffsetPoints(lwPolyline, lineWidth / 2);
                Vector2[] outerV2s = new Vector2[innerV2s.Length];
                Vector2 currentV2;
                Solid solid;
                for (int i = 0; i < innerV2s.Length; i++)
                {
                    currentV2 = vector2s[i];
                    outerV2s[i] = fun.Polar(currentV2, Vector2.Angle(innerV2s[i], currentV2), lineWidth / 2);
                }

                for (int i = 0; i < vector2s.Count; i++)
                {
                    if (i < vector2s.Count - 1)
                    {
                        solid = new Solid(innerV2s[i], outerV2s[i], innerV2s[i + 1], outerV2s[i + 1]);
                        solid.Layer = layer;
                        dxf.AddEntity(solid);
                    }
                    else
                    {
                        solid = new Solid(innerV2s[i], outerV2s[i], innerV2s[0], outerV2s[0]);
                        solid.Layer = layer;
                        dxf.AddEntity(solid);
                    }
                }

            }
            else
            {
                LightFillPline(dxf, vector2s, lineWidth, layer);
            }
        }
        /// <summary>
        /// 引用改造
        /// </summary>
        /// <param name="v3"></param>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <param name="z"></param>
        /// <returns></returns>
        public static Vector3 ReferenceV3(Vector3 v3, double x, double y, double z)
        {
            return new Vector3(v3.X + x, v3.Y + y, v3.Z + z);
        }
        public static Vector3 ReferenceV3(Vector2 v2, double x, double y, double z)
        {
            return new Vector3(v2.X + x, v2.Y + y, z);
        }
        /// <summary>
        /// 两点确定的单位向量
        /// </summary>
        /// <param name="start"></param>
        /// <param name="end"></param>
        /// <returns></returns>
        public static Vector3 UnitVector(Vector3 start,Vector3 end)
        {
            double dis = Vector3.Distance(start, end);
            if (dis == 0)
                throw new Exception("两向量为相同向量");
            Vector3 v = end - start;
            return new Vector3(v.X / dis, v.Y / dis, v.Z / dis);
        }
        /// <summary>
        /// 获取三维向量的二维投影XY 即：去掉z坐标
        /// </summary>
        /// <param name="vector3"></param>
        /// <returns></returns>
        public static Vector2 ToV2(Vector3 vector3) {
            return new Vector2(vector3.X, vector3.Y);
        }
        /// <summary>
        /// 给二维向量＋一个维度，返回三维向量
        /// </summary>
        /// <param name="v2"></param>
        /// <param name="z"></param>
        /// <returns></returns>
        public static Vector3 ToV3(Vector2 v2, double z)
        {
            return new Vector3(v2.X, v2.Y, z);
        }
        public static Vector3 ToV3(Vector3 v2, double z)
        {
            return new Vector3(v2.X, v2.Y, z);
        }
        /// <summary>
        /// 投影角度
        /// </summary>
        /// <param name="p1"></param>
        /// <param name="p2"></param>
        /// <returns></returns>
        public static double AngleOnP(Vector3 p1, Vector3 p2)
        {
            return Vector2.Angle(new Vector2(p1.X, p1.Y), new Vector2(p2.X, p2.Y));
        }
        /// <summary>
        /// 投影交点
        /// </summary>
        /// <param name="p1"></param>
        /// <param name="p2"></param>
        /// <param name="p3"></param>
        /// <param name="p4"></param>
        /// <returns></returns>
        public static Vector2 IntersOnP(Vector3 p1,Vector3 p2,Vector3 p3,Vector3 p4)
        {
            return fun.Inters(new Vector2(p1.X, p1.Y), new Vector2(p2.X, p2.Y), new Vector2(p3.X, p3.Y), new Vector2(p4.X, p4.Y));
        }
        /// <summary>
        /// 偏移
        /// </summary>
        /// <param name="voff"></param>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static Vector3 OffsetXY(Vector3 voff,Vector3 obj) {
            return new Vector3(obj.X + voff.X, obj.Y + voff.Y, obj.Z + voff.Z);
        }
        /// <summary>
        /// 求平面单位法向量，参数建议使用new Face3d（p1,p2,p3）,以便知道单位法向量的穿透方向
        /// </summary>
        /// <param name="face"></param>
        /// <returns></returns>
        public static Vector3 UnitNormal(Face3d face)
        {
            Vector3 p1 = face.FirstVertex;
            Vector3 p2 = face.SecondVertex;
            Vector3 p3 = face.ThirdVertex;

            Vector3 v21 = p2 - p1;
            Vector3 v31 = p3 - p1;

            double dis21 = Vector3.Distance(p1, p2);
            double dis31 = Vector3.Distance(p1, p3);

            Vector3 u21 = new Vector3(v21.X / dis21, v21.Y / dis21, v21.Z / dis21);
            Vector3 u31 = new Vector3(v31.X / dis31, v31.Y / dis31, v31.Z / dis31);

            return Vector3.CrossProduct(u21, u31);
        }
        /// <summary>
        /// 求平面法向量，非单位法向量
        /// </summary>
        /// <param name="face"></param>
        /// <returns></returns>
        public static Vector3 Normal4Face3d(Face3d face) {

            Vector3 p1 = face.FirstVertex;
            Vector3 p2 = face.SecondVertex;
            Vector3 p3 = face.ThirdVertex;

            Vector3 v1 = p2 - p1;
            Vector3 v2 = p3 - p1;

            return Vector3.CrossProduct(v1,v2);
        }
        /// <summary>
        /// Rodrigue旋转向量公式：rotate是旋转轴上的!!!单位向量!!!，k是缩放率，thetaR是右手定则下旋转角度,obj被旋转向量
        /// </summary>
        public static Vector3 Rodrigue(Vector3 rotate,double k,double thetaR,Vector3 obj) {

            rotate = k * rotate;

            Vector3 rotated = Math.Cos(thetaR) * obj + (1 - Math.Cos(thetaR)) * Vector3.DotProduct(obj, rotate) * rotate + Math.Sin(thetaR) * Vector3.CrossProduct(rotate, obj);

            return rotated;
        }
        /// <summary>
        /// 空间直线与平面的交点
        /// </summary>
        /// <param name="face3D"></param>
        /// <param name="line"></param>
        /// <returns></returns>
        public static Vector3 Inters(Face3d face3D, Line line) {

            //空间平面的点法式表示,即平面上任意点与法向量点乘的值为0

            //平面法向量
            Vector3 normal = Normal4Face3d(face3D);

            //包含了直线方向和两点距离两种信息的向量
            Vector3 endp = line.EndPoint;
            Vector3 stap = line.StartPoint;
            Vector3 vline = new Vector3(endp.X - stap.X, endp.Y - stap.Y, endp.Z - stap.Z);

            //若直线与法向量垂直，说明直线平行平面，有零个或无穷个交点
            double dotProduct = Vector3.DotProduct(normal, vline);
            if ( dotProduct == 0)
            {
                return Vector3.NaN;
            }

            Vector3 p1 = face3D.FirstVertex;

            //t相当交点在起始点之间的比例=面积（点乘）的比例
            double t = ((p1.X - stap.X) * normal.X + (p1.Y - stap.Y) * normal.Y + (p1.Z - stap.Z) * normal.Z) / dotProduct;

            double x = stap.X + t * vline.X;
            double y = stap.Y + t * vline.Y;
            double z = stap.Z + t * vline.Z;

            return new Vector3(x, y, z);

        }
        public static Vector3 Inters(Face3d face,Vector3 v1,Vector3 v2)
        {
            if (v1.Equals(v2))
                throw new Exception("两个向量为相同向量");
            return Inters(face, new Line(v1, v2));
        }
        public static Line Inters(Face3d f1, Face3d f2, Vector3 p1) {
            //f1的法向量
            Vector3 f1normal = Normal4Face3d(f1);
            Vector3 f2normal = Normal4Face3d(f2);
            //f1，f2交线向量
            Vector3 linev = Vector3.CrossProduct(f1normal, f2normal);
            return new Line(p1, p1 + linev);
        }
        /// <summary>
        /// 返回°数
        /// </summary>
        /// <param name="sp"></param>
        /// <param name="ep"></param>
        /// <returns></returns>
        public static double Degree(Vector2 sp,Vector2 ep)
        {
            return Vector2.Angle(sp, ep) * 180 / pi;
        }
        public static double Degree(Vector3 p1, Vector3 p2)
        {
            return Degree(new Vector2(p1.X, p1.Y), new Vector2(p2.X, p2.Y));
        }
        /// <summary>
        /// 正三角形刀片内接圆返回边长
        /// </summary>
        /// <param name="ic"></param>
        /// <returns></returns>
        public static double GetLByTIC(double ic) {
            return Math.Tan(60 * pi / 180) * ic;
        }
        /// <summary>
        /// 六边形刀片内接圆求边长
        /// </summary>
        /// <param name="ic"></param>
        /// <param name="epsr"></param>
        /// <returns></returns>
        public static double GetLByHIC(double ic)
        {
            return ic / 2 * ( Math.Tan(50 * pi / 180) + Math.Tan(10 * pi / 180));
        }
        /// <summary>
        /// 根据内接圆直径计算菱形边长
        /// </summary>
        /// <param name="ic"></param>
        /// <param name="epsr"></param>
        /// <returns></returns>
        public static double GetLByIC(double ic, double epsr)
        {
            return ic / 2 * (1 / Math.Tan(epsr / 2) + Math.Tan(epsr / 2));
        }
        /// <summary>
        /// 根据内接圆直径计算等边形刀片边长
        /// </summary>
        /// <param name="ic"></param>
        /// <param name="n"></param>
        /// <returns></returns>
        public static double GetLByIC2(double ic, double n)
        {
            return ic * Math.Tan(180 * pi / 180 / n);
        }
        /// <summary>
        /// 针对lowwer视图投影的方法,n:表示n条边 [0,n)表示顶面的点，[n,2n)表示底面的点，其他是其余点
        /// </summary>
        /// <param name="oli4"></param>
        /// <param name="gamao"></param>
        /// <param name="lambdas"></param>
        /// <param name="s"></param>
        /// <param name="rYr"></param>
        /// <param name="points"></param>
        /// <returns></returns>
        public static Vector2[] Diamonds3d(Vector2 oli4, double gamao, double lambdas, double s, double rYr, int n, bool leftview, params Vector2[] points) {

            /// 本方法中的坐标系为右手坐标系
            ///             y
            ///             |
            ///             |__ __ x
            ///             /
            ///            /
            ///           z 

            //将i4平移到原点
            int num = points.Length;
            double originx = points[0].X;
            double originy = points[0].Y;
            for (int i = 0; i < num; i++)
            {
                points[i].X -= originx;
                points[i].Y -= originy;
            }
            //放平
            double theta = -90 * pi / 180;
            Matrix3 trans = new Matrix3(
                1, 0, 0,
                0, Math.Cos(theta), -Math.Sin(theta),
                0, Math.Sin(theta), Math.Cos(theta));

            //绕y轴旋转（A），使得主切削刃移动到x轴上，便可绕z轴旋转形成刃倾角，完了再做A逆
            //A
            Matrix3 rYtrans = new Matrix3(
                Math.Cos(rYr), 0, -Math.Sin(rYr),
                            0, 1, 0,
                Math.Sin(rYr), 0, Math.Cos(rYr));

            //绕x轴旋转形成前角
            double rXr = gamao;
            Matrix3 rXtrans = new Matrix3(
                1, 0, 0,
                0, Math.Cos(rXr), -Math.Sin(rXr),
                0, Math.Sin(rXr), Math.Cos(rXr));

            //绕z轴旋转形成刃倾角
            double rZr = lambdas;
            Matrix3 rZtrans = new Matrix3(
                Math.Cos(rZr), -Math.Sin(rZr), 0,
                Math.Sin(rZr),  Math.Cos(rZr), 0,
                            0,              0, 1);

            //A逆
            Matrix3 rYtransN = rYtrans.Inverse();

            
            Vector3[] points3d = new Vector3[num];
            for (int i = 0; i < num; i++)
            {
                if (i >= n && i < 2 * n)
                {
                    //
                    points3d[i] = rYtransN * rZtrans * rXtrans * rYtrans * trans * new Vector3(points[i].X, points[i].Y, -s);
                }
                else
                {
                    //
                    points3d[i] = rYtransN * rZtrans * rXtrans * rYtrans * trans * new Vector3(points[i].X, points[i].Y, 0);
                }


            }

            /// 本方法中的坐标系为右手坐标系
            ///             y
            ///             |
            ///             |__ __ x
            ///             /
            ///            /
            ///           z 
            ///           

            if (leftview) {

                //立正,即绕x轴旋转90度
                Matrix3 attention = new Matrix3(
                    1,  0,   0,
                    0,  0,  -1,
                    0,  1,   0);

                //向右转
                Matrix3 turnRight = new Matrix3(
                        0,  0,  1,
                        0,  1,  0,
                       -1,  0,  0);

                for (int i = 0; i < num; i++) {
                    points3d[i] = turnRight * attention * points3d[i];
                }
            }

            Vector2[] afterTrans = new Vector2[num];
            for (int i = 0; i < num; i++)
            {
                afterTrans[i] = new Vector2(points3d[i].X + oli4.X, points3d[i].Y + oli4.Y);
            }

            return afterTrans;
        }
        /// <summary>
        /// 线性变换
        /// </summary>
        /// <param name="trans"></param>
        /// <param name="lwPolyline"></param>
        public static Vector3 LinearTrans(double k,Vector3 obj) {
            return new Vector3(obj.X * k, obj.Y * k, obj.Z * k);
        }
        public static void LinearTrans(Matrix3 trans, LwPolyline lwPolyline) {
            
            List<LwPolylineVertex> vertices = lwPolyline.Vertexes;
            int num = vertices.Count;
            for (int i = 0; i < num; i++) {
                Vector3 vector3 = trans * new Vector3(vertices[i].Position.X, vertices[i].Position.Y, 0);
                vertices[i].Position = new Vector2(vector3.X, vector3.Y);
            }
        }
        public static Vector2 LinearTrans(Matrix3 trans, Vector2 points) {
            Vector3 vector3 = trans * new Vector3(points.X, points.Y, 0);
            return new Vector2(vector3.X, vector3.Y);
        }
        /// <summary>
        /// 将lwpolyline变成vector2数组，可用来做drawplineofw的参数
        /// </summary>
        /// <param name="lwPolyline"></param>
        /// <returns></returns>
        public static Vector2[] GetV2ArrayFromLwPolyline(LwPolyline lwPolyline) {
            List<LwPolylineVertex> vertices = lwPolyline.Vertexes;
            int num = vertices.Count;
            if (num == 0)
                throw new Exception("多段线中vector2对象个数为零");
            Vector2[] v2array = new Vector2[num];
            for (int i = 0; i < num; i++) {
                v2array[i] = vertices[i].Position;
            }
            return v2array;
        }
        /// <summary>
        /// 画等边六边形刀片 flag:是否侧切
        /// </summary>
        /// <param name="i1"></param>
        /// <param name="l3"></param>
        /// <param name="insertAglR"></param>
        /// <param name="cutAglR"></param>
        /// <param name="flag"></param>
        /// <returns></returns>
        public static Vector2[] Hexagonal(Vector2 i6, double l3, double insertAglR, double cutAglR, bool flag) {
            //第一点i1到第二点的角度
            double firstAgl;
            if (flag)
                firstAgl = cutAglR - pi / 2;
            else
                firstAgl = pi - cutAglR - insertAglR;
            double bR = pi - insertAglR;
            double sR = pi - pi / 3 - bR;
            Vector2 i1 = fun.Polar(i6, firstAgl, l3);
            LwPolyline hexInsert = new LwPolyline();
            Vector2[] points = new Vector2[6];
            points[0] = i6;
            points[1] = i1;
            //目标点
            double oR = firstAgl;
            for (int i = 2; i < 6; i++) {
                if (i % 2 == 0)
                {
                    oR = oR + sR;

                }
                else
                {
                    oR = oR + bR;
                }
                points[i] = fun.Polar(points[i - 1], oR, l3);
            }
            return points;
        }
        public static Vector2[] HexagonalV(Vector2 i1, double l3, double insertAglR, double cutAglR, bool flag)
        {
            Vector2[] points = Hexagonal(i1, l3, insertAglR, cutAglR, flag);
            return ToVertical(points[0], pi / 2, points);
        }
        /// <summary>
        /// 线段起始点到线段上选定点的距离 ：线段距离 = k,！！！k值不要取分数！！！
        /// </summary>
        /// <param name="startPoint"></param>
        /// <param name="endPoint"></param>
        /// <param name="k"></param>
        /// <returns></returns>
        public static Vector2 KPoint(Vector2 startPoint,Vector2 endPoint,double k) {
            double x = startPoint.X + k * (endPoint.X - startPoint.X);
            double y = startPoint.Y + k * (endPoint.Y - startPoint.Y);
            return new Vector2(x,y);
        }
        public static Vector3 KPoint(Vector3 startPoint, Vector3 endPoint, double k) {
            double x = startPoint.X + k * (endPoint.X - startPoint.X);
            double y = startPoint.Y + k * (endPoint.Y - startPoint.Y);
            double z = startPoint.Z + k * (endPoint.Z - startPoint.Z);
            return new Vector3(x, y, z);
        }
        public static Vector2 HalfPoint(Vector2 startPoint, Vector2 endPoint)
        {
            double x = startPoint.X + 0.5 * (endPoint.X - startPoint.X);
            double y = startPoint.Y + 0.5 * (endPoint.Y - startPoint.Y);
            return new Vector2(x, y);
        }
        /// <summary>
        /// 小角度标注,适用于（0）-10 degree
        /// </summary>
        /// <param name="dxf"></param>
        /// <param name="startLine"></param>
        /// <param name="endLine"></param>
        /// <param name="offset"></param>
        /// <param name="dimStyle"></param>
        public static void NeedleDim(DxfDocument dxf,Line startLine,Line endLine,Double offset,String text,double dim,DimensionStyle dimStyle) 
        {
            Vector2 point = Xpoint(startLine, endLine);
            //起始线，起始点
            Vector2 startLine0 = new Vector2(startLine.StartPoint.X, startLine.StartPoint.Y);
            //起始线，终止点
            Vector2 startLine1 = new Vector2(startLine.EndPoint.X, startLine.EndPoint.Y);
            //终止线，起始点
            Vector2 endLine0 = new Vector2(endLine.StartPoint.X, endLine.StartPoint.Y);
            //终止线，终止点
            Vector2 endLine1 = new Vector2(endLine.EndPoint.X, endLine.EndPoint.Y);
            double startagl = Vector2.Angle(startLine0, startLine1);
            double endagl = Vector2.Angle(endLine0, endLine1);
            double dif = endagl - startagl;
            if(dif==0||dif==pi)
                throw new Exception("共线");
            double temp = 0;
            if (dif < 0)
            {
                temp = endagl;
                endagl = startagl;
                startagl = temp;
            }
            dif = endagl - startagl;
            if (dif > pi / 180 * 90 && dif < pi)
            {
                temp = startagl;
                startagl = endagl;
                endagl = temp + pi;
            }
            else if (dif > pi && dif < 3 * pi / 2)
            {
                startagl = startagl + pi;
            }
            else if (dif >= 3 * pi / 2 && dif < pi * 2)
            {
                temp = endagl;
                endagl = startagl;
                startagl = temp;
            }
            Arc dimarc = new Arc(point, offset, startagl * 180 / pi, endagl * 180 / pi);
            dxf.AddEntity(dimarc);
            //箭头
            Vector2 startPoint = fun.Polar(point, startagl, offset);
            Vector2 endPoint = fun.Polar(point, endagl, offset);
            // dxf.AddEntity(MyArrow(startPoint,startagl * 180 / pi - 90,1,1.5));
            // dxf.AddEntity(MyArrow(endPoint, endagl * 180 / pi + 90, 1, 1.5));
            dxf.AddEntity(MyArrow(startPoint,startagl * 180 / pi - 90,dimStyle.ArrowSize * 2,dimStyle.ArrowSize * 5));
            dxf.AddEntity(MyArrow(endPoint, endagl * 180 / pi + 90, dimStyle.ArrowSize * 2, dimStyle.ArrowSize * 5));
            //文字
            Text txt;
            if (text != null && text != "") 
            {
                txt = new Text(text, fun.Polar(startPoint, startagl - pi / 4, 1 + dimStyle.TextHeight), dimStyle.TextHeight, startagl);
                if (startagl > pi / 2 && startagl < pi * 3 / 2)
                {
                    txt.Alignment = TextAlignment.BottomRight;
                }
                else
                    txt.Alignment = TextAlignment.TopLeft;
                dxf.AddEntity(txt);
            }
            if (!dim.Equals(double.NaN)) {
                txt = new Text(dim+"", fun.Polar(endPoint, endagl + pi / 4, 3 + dimStyle.TextHeight), dimStyle.TextHeight, endagl);
                dxf.AddEntity(txt);
            }
            //延长线
            dxf.AddEntity(new Line(point, fun.Polar(point, startagl, offset + 0.25)));
            dxf.AddEntity(new Line(point, fun.Polar(point, endagl, offset + 0.25)));
             
        }
        public static void NeedleDim(DxfDocument dxf, Line startLine, Line endLine,Double offset, String text,  DimensionStyle dimStyle) 
        {
            NeedleDim(dxf, startLine, endLine, offset, text, double.NaN, dimStyle);
        }
        public static void NeedleDim(DxfDocument dxf, Line startLine, Line endLine, Double offset, double dim, DimensionStyle dimStyle) {
            NeedleDim(dxf, startLine, endLine, offset, null, dim, dimStyle);
        }
        /// <summary>
        /// 两直线交点
        /// </summary>
        /// <param name="line1"></param>
        /// <param name="line2"></param>
        /// <returns></returns>
        public static Vector2 Xpoint(Line line1, Line line2) {
            return fun.Inters(new Vector2( line1.StartPoint.X, line1.StartPoint.Y), new Vector2( line1.EndPoint.X,line1.EndPoint.Y),
                new Vector2(line2.StartPoint.X, line2.StartPoint.Y), new Vector2(line2.EndPoint.X, line2.EndPoint.Y));
        }
        //三阶贝塞尔曲线,
        public static LwPolyline Beizer2(float kStep, params Vector2[] controlPoints)
        {
            LwPolyline bline = new LwPolyline();
            for (int i = 0; i < controlPoints.Length - 2; i += 2)
            {
                for (float k = 0.0f; k <= 1.0f; k += kStep)
                {

                    double agl1 = Vector2.Angle(controlPoints[i], controlPoints[i + 1]);
                    double dis1 = Vector2.Distance(controlPoints[i], controlPoints[i + 1]);
                    Vector2 v1 = fun.Polar(controlPoints[i], agl1, k * dis1);

                    double agl2 = Vector2.Angle(controlPoints[i + 1], controlPoints[i + 2]);
                    double dis2 = Vector2.Distance(controlPoints[i + 1], controlPoints[i + 2]);
                    Vector2 v2 = fun.Polar(controlPoints[i + 1], agl2, k * dis2);

                    double agl3 = Vector2.Angle(controlPoints[i + 2], controlPoints[i + 3]);
                    double dis3 = Vector2.Distance(controlPoints[i + 2], controlPoints[i + 3]);
                    Vector2 v3 = fun.Polar(controlPoints[i + 2], agl3, k * dis3);

                    bline.Vertexes.Add(new LwPolylineVertex());
                }
            }
            return bline;
        }
        private static Vector2 bezier3func(double uu, Vector2[] pp)
        {
            Vector2 part0 = new Vector2(pp[0].X * uu * uu * uu, pp[0].Y * uu * uu * uu);
            Vector2 part1 = new Vector2(pp[1].X * 3 * uu * uu * (1 - uu), pp[1].Y * 3 * uu * uu * (1 - uu));
            Vector2 part2 = new Vector2(pp[2].X * 3 * uu * (1 - uu) * (1 - uu), pp[2].Y * 3 * uu * (1 - uu) * (1 - uu));
            Vector2 part3 = new Vector2(pp[3].X * (1 - uu) * (1 - uu) * (1 - uu), pp[3].Y * (1 - uu) * (1 - uu) * (1 - uu));
            return new Vector2(part0.X + part1.X + part2.X + part3.X, part0.Y + part1.Y + part2.Y + part3.Y);
        }
        //通过两点生成反7字的11个spline的点,从左下到右上
        public static Vector2[] Recoil(Vector2 startPoint,Vector2 endPoint) {
            Vector2[] splinePoints = new Vector2[11];
            Vector2 x = new Vector2(startPoint.X, endPoint.Y);
            splinePoints[0] = startPoint;
            splinePoints[5] = x;
            splinePoints[10] = endPoint;
            Random ra = new Random();
            for (int i = 1; i < 5; i++) {
                splinePoints[i] = new Vector2(startPoint.X + ra.Next(-7, 7)/5.3, startPoint.Y + (endPoint.Y - startPoint.Y) / 5 * i);
                splinePoints[i + 5] = new Vector2(startPoint.X + (endPoint.X - startPoint.X) / 5 * i, endPoint.Y + ra.Next(-7, 7)/5.3);
            }
            return splinePoints;
        }
        //通过两点生成一个趋势为直线的样条,num为控制点个数，a为振幅
        /// <summary>
        /// num：控制点个数
        /// a/9.3为振幅
        /// </summary>
        /// <param name="startPoint"></param>
        /// <param name="endPoint"></param>
        /// <param name="num"></param>
        /// <param name="a"></param>
        /// <returns></returns>
        public static Spline TwoPointsSpline(Vector2 startPoint, Vector2 endPoint ,int num , int a) {
            //生成另外的num-2个控制点
            Vector2[] cps = new Vector2[num];
            cps[0] = startPoint;
            cps[num - 1] = endPoint;
            Random ra = new Random();
            for (int i = 1; i < num - 1; i++) {
                cps[i] = new Vector2((endPoint.X - startPoint.X) / (num - 1) * i + startPoint.X, (endPoint.Y - startPoint.Y) / (num - 1) * i + startPoint.Y + ra.Next(-a, a) / 9.3);
            }
            List<SplineVertex> vertices = AddpointsToSpline(cps);
            Spline spline = new Spline(vertices);
            return spline;
        }
        public static Spline TwoPointsSpline(Vector2 startPoint, Vector2 endPoint) {
            return TwoPointsSpline( startPoint, endPoint,15, 9);
        }
        //波浪线
        /// <summary>
        /// num:控制点个数
        /// a:表示振动幅度
        /// </summary>
        public static Spline TwoPointsWaveline(Vector2 startPoint, Vector2 endPoint, int num, double a)
        {
            //生成另外的num-2个控制点
            Vector2[] cps = new Vector2[num];
            cps[0] = startPoint;
            cps[num - 1] = endPoint;
            for (int i = 1; i < num - 1; i++)
            {
                cps[i] = new Vector2((endPoint.X - startPoint.X) / (num - 1) * i + startPoint.X, (endPoint.Y - startPoint.Y) / (num - 1) * i + startPoint.Y + a * Math.Pow(-1,i));
            }
            List<SplineVertex> vertices = AddpointsToSpline(cps);
            Spline spline = new Spline(vertices);
            spline.Layer = new Layer("spline");
            return spline;
        }
        //spline
        public static List<SplineVertex> AddpointsToSpline(params Vector2[] points) {
            if (points.Length == 0)
                throw new Exception("参数中至少要有一个Vector2对象");
            List<SplineVertex> vertices = new List<SplineVertex>();
            foreach (Vector2 point in points) {
                vertices.Add(new SplineVertex(point));
            }
            return vertices;
        }
        //剖切符号,从起始点到结束点，拐向逆时针方向。
        public static EntityObject[] SectionSymbol(Vector2 startpoint, Vector2 endpoint, string c)
        {
            return SectionSymbol(startpoint, endpoint, c, 4, 1, 1);
        }
        public static EntityObject[] SectionSymbol(Vector2 startpoint, Vector2 endpoint, string c,double textHeigth)
        {
            return SectionSymbol(startpoint, endpoint, c, 4, 1, textHeigth);
        }
        public static EntityObject[] SectionSymbol(Vector2 startpoint, Vector2 endpoint, string c, double totalLength, double arrowheadLength, double textHeigth)
        {
            //起点到终点向量的方向
            double s_e_a = Vector2.Angle(startpoint, endpoint);
            //+90度表示符号拐向逆时针方向
            double rotateDegree = s_e_a * 180 / Math.PI + 90;
            Vector2 tailonstart = fun.Polar(startpoint, s_e_a + Math.PI, 2);
            Vector2 tailonend = fun.Polar(endpoint, s_e_a, 2);
            //箭头顶点
            Vector2 pointonstart = fun.Polar(tailonstart, rotateDegree * Math.PI / 180, totalLength);
            EntityObject[] startarrow = MyArrow(pointonstart, -90 + s_e_a * 180 / Math.PI, 1, totalLength);
            Line startline = new Line(startpoint, tailonstart);
            //箭头顶点
            Vector2 pointonend = fun.Polar(tailonend, rotateDegree * Math.PI / 180, totalLength);
            EntityObject[] endarrow = MyArrow(pointonend, -90 + s_e_a * 180 / Math.PI, 1, totalLength);
            Line endline = new Line(endpoint, tailonend);
            //文字
            Text endtext = new Text(c, fun.Polar(endpoint, Vector2.Angle(endpoint, pointonend), Vector2.Distance(endpoint, pointonend) + 1), textHeigth, s_e_a * 180 / Math.PI);
            Vector2 endtextP = new Vector2(endtext.Position.X, endtext.Position.Y);
            Text starttext = new Text(c, fun.Polar(endtextP,Vector2.Angle(endpoint, startpoint), Vector2.Distance(pointonend, pointonstart) + Vector2.Distance(endtextP,pointonend)*2 + textHeigth *0.2),
                textHeigth, s_e_a * 180 / Math.PI);
            return new EntityObject[] { startarrow[0], startarrow[1], startline, endarrow[0], endarrow[1], endline, starttext, endtext };
        }
        //箭头
        /// <summary>
        /// 画箭头,point：箭头顶点位置；rotateDegree:绕point旋转角度（D）；arrowheadLength:箭头长度；totalLength：总长
        /// </summary>
        /// <param name="point"></param>
        /// <param name="rotateDegree"></param>
        /// <param name="arrowheadLength"></param>
        /// <param name="totalLength"></param>
        /// <returns></returns>
        public static EntityObject[] MyArrow(Vector2 point, double rotateDegree, double arrowheadLength, double totalLength)
        {
            //
            double pi = Math.PI;
            double angle = Math.Atan(0.5 / 3) * 2 * 180 / pi;
            Vector2 t1 = fun.Polar(point, (angle / 2 + rotateDegree) * pi / 180, arrowheadLength / Math.Cos(angle / 2 * pi / 180));
            Vector2 t2 = fun.Polar(point, (rotateDegree - angle / 2) * pi / 180, arrowheadLength / Math.Cos(angle / 2 * pi / 180));
            Solid arrowhead = new Solid(point, t1, t2)
            {
                Layer = Layer.Default,
                Linetype = Linetype.ByBlock,
                Color = AciColor.ByBlock,
                Lineweight = Lineweight.ByBlock
            };
            Vector2 t1_2 = fun.Polar(point, rotateDegree * pi / 180, arrowheadLength);
            Vector2 tail = fun.Polar(point, rotateDegree * pi / 180, totalLength);
            Line line = new Line(t1_2, tail);
            return new EntityObject[] { arrowhead, line };
        }
        //存在刃倾角时,刀片在俯视图上的投影（x轴坐标改变）,以刀尖所在点所在线旋转.
        public static void ContourWithLambdas(LwPolyline insertContour, double lambdas)
        {
            //刀尖所在点的x坐标
            lambdas = lambdas * Math.PI / 180;
            double x = insertContour.Vertexes[0].Position.X;
            int num = insertContour.Vertexes.Count;
            for (int i = 1; i < num; i++)
            {
                insertContour.Vertexes[i].Position = new Vector2((insertContour.Vertexes[i].Position.X - x) * Math.Tan(lambdas) + x,
                    insertContour.Vertexes[i].Position.Y);
            }
        }
        /// <summary>
        /// 画正三角形，可用于T型刀片,刀尖位置i1,边长l3，是否侧切flag，与切削方向夹角pAgl
        /// </summary>
        /// <param name="i3"></param>
        /// <param name="l3"></param>
        /// <param name="flag"></param>
        /// <param name="pAgl"></param>
        /// <returns></returns>
        public static Vector2[] TrianglePoints(Vector2 i1, double l3, bool flag, double pAgl)
        {
            double pi = Math.PI;
            double agl_i1_i2 = 0;
            if (flag)
                agl_i1_i2 = pAgl - pi / 2;
            else
                agl_i1_i2 = pi - pAgl - pi / 3;
            Vector2 i2 = fun.Polar(i1, agl_i1_i2, l3);
            double agl_i2_i3 = agl_i1_i2 + pi - pi / 3;
            Vector2 i3 = fun.Polar(i2, agl_i2_i3, l3);
            return new Vector2[] { i1, i2, i3 };
        }
        //画菱形，可用于C型刀片,通过刀尖位置i4确定，l3表示边长，insertAngle表示刀尖夹角.flag为真-侧切，flag为假-端切，pagl是切刃与切削方向夹角
        //侧切时，i4-i1为切削刃，端切时i3-i4为切削刃
        public static Vector2[] DiamondPoints(Vector2 i4, double l3, double insertAngle, bool flag, double pAgl)
        {
            double agl_i4_i1 = 0;
            if (flag)
                agl_i4_i1 = pAgl - Math.PI / 2;
            else
                agl_i4_i1 = Math.PI - pAgl - insertAngle;
            //Console.Write(agl_i4_i1 * 180 / Math.PI);
            //Console.ReadKey();
            Vector2 i1 = fun.Polar(i4, agl_i4_i1, l3);
            double agl_i1_i2 = agl_i4_i1 + insertAngle;
            Vector2 i2 = fun.Polar(i1, agl_i1_i2, l3);
            double agl_i2_i3 = agl_i1_i2 + Math.PI - insertAngle;
            Vector2 i3 = fun.Polar(i2, agl_i2_i3, l3);
            return new Vector2[] { i4, i1, i2, i3 };
        }
        //竖直排版时，绕第一点逆时针旋转90度
        /// <summary>
        /// 立式图画◇刀片（radian）
        /// </summary>
        /// <param name="i4">刀尖点</param>
        /// <param name="l3">理论边长</param>
        /// <param name="insertAngle">刀尖角（radian）</param>
        /// <param name="flag">是否侧切</param>
        /// <param name="pAgl">主偏角</param>
        /// <returns></returns>
        public static Vector2[] DiamondPointsV(Vector2 i4, double l3, double insertAngle, bool flag, double pAgl) {
            Vector2[] points = DiamondPoints(i4,  l3,  insertAngle,  flag,  pAgl);
            return ToVertical(points[0], Math.PI / 2, points);
        }
        /// <summary>
        /// !!!由于返回的数组中第一个点是center，要注意数组中第一个点，第二个点可能是同一个点，以返回结果作参数时须谨慎!!!
        /// 返回的数组，角标为0的点是旋转点，从角标1开始依次是被旋转的点.
        /// </summary>
        /// <param name="center"></param>
        /// <param name="rotateR"></param>
        /// <param name="points"></param>
        /// <returns>角标为0的点是旋转点，从角标1开始依次是被旋转的点</returns>
        public static Vector2[] RotateByPoint(Vector2 center, double rotateR, params Vector2[] points)
        {
            Vector2[] originPoints = ToVertical(center, rotateR, points);
            Vector2[] offsetPoints = new Vector2[originPoints.Length+1];
            offsetPoints[0] = center;
            for (int i = 1; i < offsetPoints.Length; i++) {
                offsetPoints[i] = originPoints[i - 1];
            }
            return offsetPoints;
        }
        /// <summary>
        /// 绕center旋转，返回的数组中理论上是不包含center（除非以points中某个点为旋转点）
        /// </summary>
        /// <param name="center"></param>
        /// <param name="rotateR"></param>
        /// <param name="points"></param>
        /// <returns></returns>
        public static Vector2[] ToVertical(Vector2 center, double rotateR ,params Vector2[] points ) {
            int num = points.Length;
            Vector2[] vpoints = new Vector2[num];
            double dis;
            double agl;
            for (int i = 0; i < num; i++) {
                dis = Vector2.Distance(center, points[i]);
                agl = Vector2.Angle(center, points[i]) + rotateR;
                vpoints[i] = fun.Polar(center, agl, dis);
            }
            return vpoints;
        }
        /// <summary>
        /// 闭合多段线向内偏移后的各点,!!!请勿使用相同点作为相邻两点!!!
        /// </summary>
        /// <param name="offset"></param>
        /// <param name="points"></param>
        /// <returns></returns>
        public static Vector2[] OffsetPoints(double offset, params Vector2[] points)
        {
            int num = points.Length;
            Vector2[] after = new Vector2[num];
            Vector2 p0;
            Vector2 p1;
            Vector2 p2;
            for (int i = 0; i < num; i++)
            {
                if (i == 0)
                    p0 = points[num - 1];
                else
                    p0 = points[i - 1];
                p1 = points[i];
                if (i == num - 1)
                    p2 = points[0];
                else
                    p2 = points[i + 1];
                double half_angle = ThreePointsAngle(p0, p1, p2) / 2;
                double agl_p1_p2 = Vector2.Angle(p1, p2);
                double dis = offset / Math.Sin(half_angle);
                after[i] = fun.Polar(p1, half_angle + agl_p1_p2, dis);
            }
            return after;
        }
        public static Vector2[] OffsetPoints(LwPolyline polyline, double offset)
        {
            List<LwPolylineVertex> vertices = polyline.Vertexes;
            int num = vertices.Count;
            Vector2[] points = new Vector2[num];
            for (int i = 0; i < num; i++)
            {
                points[i] = vertices[i].Position;
            }
            return OffsetPoints(offset, points);
        }
        //从多段线中拿到第n个圆弧,从1开始
        public static Arc GetArcFromPline(LwPolyline polyline, int num)
        {
            if (num <= 0)
                throw new Exception("参数应该为正整数");
            List<EntityObject> curves = polyline.Explode();
            int count = curves.Count;
            int k = 0;
            for (int i = 0; i < count; i++)
            {
                if (curves[i].Type.ToString() == "Arc")
                    k++;
                if (k == num)
                    return (Arc)curves[i];
            }
            throw new Exception("共找到" + k + "个圆弧对象，" + "未找逆时针方向到第" + num + "个圆弧");
        }
        //给多段线中的某个圆弧标注,不包含标注内容与位置,theArc表示第几个圆弧，从1开始，按多段线顺序计数。
        public static RadialDimension ReDimension(LwPolyline polyline, int theArc, DimensionStyle dimensionStyle)
        {
            return ReDimension(polyline, theArc, dimensionStyle, 0);
        }
       /// <summary>
       /// 给多段线中的某个圆弧标注,不包含标注内容与位置,theArc表示第几个圆弧，从1开始，按多段线顺序计数。
       /// </summary>
       /// <param name="polyline">多段线</param>
       /// <param name="theArc">多段线的第几个圆弧</param>
       /// <param name="dimensionStyle">标注形式</param>
       /// <param name="rotationD">逆时针，degree</param>
       /// <returns></returns>
       /// <exception cref="Exception"></exception>
        public static RadialDimension ReDimension(LwPolyline polyline, int theArc, DimensionStyle dimensionStyle,double rotationD)
        {
            return ReDimension(polyline, theArc, dimensionStyle, rotationD, 7);
        }
       
       /// <summary>
       /// 给多段线中的某个圆弧标注,不包含标注内容与位置,theArc表示第几个圆弧，从1开始，按多段线顺序计数。
       /// </summary>
       /// <param name="polyline">多段线</param>
       /// <param name="theArc">多段线的第几个圆弧</param>
       /// <param name="dimensionStyle">标注形式</param>
       /// <param name="rotationD">逆时针，degree</param>
       /// <param name="offset">偏移距离</param>
       /// <returns></returns>
       /// <exception cref="Exception"></exception>
       public static RadialDimension ReDimension(LwPolyline polyline, int theArc, DimensionStyle dimensionStyle,double rotationD, double offset)
       {
           if (theArc <= 0)
               throw new Exception("指定的圆弧从1开始，应当为正整数。");
           List<EntityObject> curves = polyline.Explode();
           int num = curves.Count;
           Arc[] arcs = new Arc[num];
           //找到了几个圆弧
           int how_many_Arc_found = 0;
           int i = 0;
           for (; i < num; i++)
           {
               if (curves[i].Type.ToString() == "Arc")
               {
                   arcs[i] = (Arc)curves[i];
                   how_many_Arc_found++;
               }
               if (how_many_Arc_found == theArc)
                   break;
           }
           if (how_many_Arc_found == 0)
               throw new Exception("多段线中未发现圆弧！");
           else
               return new RadialDimension(arcs[i], rotationD, offset, dimensionStyle);
       }
        //三点依次序画出的角，返回弧度
        public static double ThreePointsAngle(params Vector2[] vectors)
        {
            if (vectors.Length != 3)
                throw new Exception("参数是！！！三个！！！点");
            if (IsColline(vectors))
            {
                if (Vector2.Angle(vectors[0], vectors[1]) == Vector2.Angle(vectors[1], vectors[2]))
                    return Math.PI;
                else
                    return 0;
            }
            double a = Vector2.Distance(vectors[0], vectors[1]);
            double b = Vector2.Distance(vectors[1], vectors[2]);
            double c = Vector2.Distance(vectors[2], vectors[0]);
            //ab的夹角的余弦
            double cos_gamma = (Math.Pow(a, 2) + Math.Pow(b, 2) - Math.Pow(c, 2)) / (2 * a * b);
            return Math.Acos(cos_gamma);
        }
        /// <summary>
        /// 判断三点是否共线
        /// </summary>
        /// <param name="vectors"></param>
        /// <returns></returns>
        public static bool IsColline(params Vector2[] vectors)
        {
            if (vectors.Length != 3)
                throw new Exception("参数是！！！三个！！！点");
            Vector2 p0 = vectors[0];
            Vector2 p1 = vectors[1];
            Vector2 p2 = vectors[2];
            if (p0 == p1 && p1 == p2)
                throw new Exception("三点坐标不能相同");
            if (p0.X - p1.X == 0)
            {
                return p2.X == p1.X;
            }
            else
            {
                double k = (p0.Y - p1.Y) / (p0.X - p1.X);
                return p2.Y == k * (p2.X - p1.X) + p1.Y;
            }
            
        }
        /// <summary>
        /// 把多段线的某个角变成圆弧，对对象本身进行操作，返回值是改变之后的对象
        /// </summary>
        /// <param name="polyline"></param>
        /// <param name="startIndex"></param>
        /// <param name="re"></param>
        /// <param name="flag"></param>
        /// <returns></returns>
        public static LwPolyline AglToArc(LwPolyline polyline, int startIndex, double re, bool flag)
        {
            //原本的多段线有几个点
            List<LwPolylineVertex> verts = polyline.Vertexes;
            //原本的点的集合放到这个容器中
            List<LwPolylineVertex> origin_vertices = new List<LwPolylineVertex>();
            foreach (LwPolylineVertex vertex in verts)
            {
                origin_vertices.Add(new LwPolylineVertex(vertex.Position.X, vertex.Position.Y));
            }
            int num = origin_vertices.Count;
            #region 求圆弧始末点
            //需要将startindex点(p1点)变成圆弧
            Vector2 p0;
            if (startIndex == 0)
                p0 = origin_vertices[num - 1].Position;
            else
                p0 = origin_vertices[startIndex - 1].Position;
            Vector2 p1 = origin_vertices[startIndex].Position;
            Vector2 p2;
            if (startIndex + 1 == num)
                p2 = origin_vertices[0].Position;
            else
                p2 = origin_vertices[startIndex + 1].Position;
            double half_agl = ThreePointsAngle(p0, p1, p2) / 2;
            double dis = re / Math.Tan(half_agl);
            //第一条线与x轴的夹角
            double firstLineAgl = Vector2.Angle(p1, p0);
            double secondLineAgl = Vector2.Angle(p1, p2);
            //圆弧首末两点
            Vector2 arcStart = fun.Polar(p1, firstLineAgl, dis);
            Vector2 arcEnd = fun.Polar(p1, secondLineAgl, dis);
            #endregion
            //去掉多段线中的startindex位的点（p1点），添加圆弧首末点
            polyline.Vertexes[startIndex].Position = arcStart;
            if (startIndex + 1 == num)
                polyline.Vertexes.Add(new LwPolylineVertex(arcEnd));
            else
            {
                polyline.Vertexes[startIndex + 1].Position = arcEnd;
                //多段线中从startindex+2以后的点均由对应的origin_vertices前一位填补
                for (int i = startIndex + 2; i < num; i++)
                {
                    polyline.Vertexes[i] = origin_vertices[i - 1];
                }
                //最后使用add添加最后一个点
                polyline.Vertexes.Add(origin_vertices[num - 1]);
            }
            //flag为真，逆时针画弧
            if (flag)
                polyline.Vertexes[startIndex].Bulge = Math.Tan((Math.PI - half_agl * 2) / 4);
            else
                polyline.Vertexes[startIndex].Bulge = Math.Tan(-(Math.PI - half_agl * 2) / 4);
            return polyline;
        }
        /// <summary>
        /// 把闭合多段线的每个角变成圆弧，对对象本身进行操作，返回值是改变之后的对象
        /// </summary>
        /// <param name="polyline"></param>
        /// <param name="re"></param>
        /// <returns></returns>
        public static LwPolyline AglToArc(LwPolyline polyline,double re) {
            if (!polyline.IsClosed)
                throw new Exception("曲线未闭合");
            int num = polyline.Vertexes.Count;
            int index = 0;
            for (int i = 1; i <= num; i++)
            {
                AglToArc(polyline, index, re, true);
                index = index + 2;
            }
            return polyline;
        }
        //三点按顺序构成一个角
        public static Arc AglToArc(double re, params Vector2[] points)
        {
            //判断是否共线
            if (IsColline(points))
                throw new Exception("三点共线!");
            Vector2 p0 = points[0];
            Vector2 p1 = points[1];
            Vector2 p2 = points[2];
            double half_agl = ThreePointsAngle(p0, p1, p2) / 2;
            double dis = re / Math.Tan(half_agl);
            double dis_p1_c = re / Math.Sin(half_agl);
            //第一条线与x轴的夹角
            double firstLineAgl = Vector2.Angle(p1, p0);
            double secondLineAgl = Vector2.Angle(p1, p2);
            Vector2 center = fun.Polar(p1, (firstLineAgl + secondLineAgl) / 2, dis_p1_c);
            //圆弧首末两点
            Vector2 arcStart = fun.Polar(p1, firstLineAgl, dis);
            Vector2 arcEnd = fun.Polar(p1, secondLineAgl, dis);
            //按角度构造弧
            double startAgl = Vector2.Angle(center, arcStart);
            double endAgl = Vector2.Angle(center, arcEnd);
            return new Arc(center, re, startAgl, endAgl);
        }
        //圆与直线的交点,当直线与x轴垂直时，数组中第一个是y值较小的那个,否则，数组中第一个是x值较小的那个。
        public static Vector2[] LineXCir(Circle circle, Vector2 p1, Vector2 p2) {
            double x = circle.Center.X;
            double y = circle.Center.Y;
            Vector2 center = new Vector2(x, y);
            Arc arc = new Arc(center,circle.Radius,0,1);
            return LineXCir(arc, p1, p2);
        }
        //public static Vector2[] LineXCir(Circle circle, Vector2 p1, Vector2 p2)
        //{
        //    double cx = circle.Center.X;
        //    double cy = circle.Center.Y;
        //    double r = circle.Radius;
        //    double a = 0;
        //    double b = 0;
        //    double c = 0;
        //    double delta = 0;
        //    double x1 = 0;
        //    double x2 = 0;
        //    double y1 = 0;
        //    double y2 = 0;
        //    //直线垂直x轴时
        //    if (p1.X == p2.X)
        //    {
        //        a = 1;
        //        b = -2 * cy;
        //        c = Math.Pow(cy, 2) + Math.Pow(p1.X - cx, 2) - Math.Pow(r, 2);
        //        delta = delta = Math.Pow(b, 2) - 4 * a * c;
        //        if (delta < 0)
        //            return null;
        //        else if (delta > 0)
        //        {
        //            //x1,x2
        //            x1 = x2 = p1.X;
        //            //y1,y2
        //            y1 = (-b - Math.Sqrt(delta)) / (2 * a);
        //            y2 = (-b + Math.Sqrt(delta)) / (2 * a);
        //            return new Vector2[] { new Vector2(x1, y1), new Vector2(x2, y2) };
        //        }
        //        else
        //            y1 = -b / (2 * a);
        //        Vector2 xy = new Vector2(p1.X, y1);
        //        //返回两个相同值的原因：调用时可以不管直线与圆有几个交点，只管取y轴值最大（小）的那个点。
        //        //需要判断是不是两个相同点，需自行判断两点的坐标。
        //        return new Vector2[] { xy, xy };
        //    }
        //    //直线不垂直x轴时,直线斜率k
        //    double k = (p1.Y - p2.Y) / (p1.X - p2.X);
        //    double t = -k * p1.X + p1.Y - cy;
        //    //求值
        //    a = 1 + Math.Pow(k, 2);
        //    b = 2 * (k * t - cx);
        //    c = Math.Pow(t, 2) + Math.Pow(cx, 2) - Math.Pow(r, 2);
        //    delta = Math.Pow(b, 2) - 4 * a * c;
        //    if (delta < 0)
        //        return null;
        //    else if (delta > 0)
        //    {
        //        //x1,x2
        //        x1 = (-b - Math.Sqrt(delta)) / (2 * a);
        //        x2 = (-b + Math.Sqrt(delta)) / (2 * a);
        //        //y1,y2
        //        y1 = k * (x1 - p1.X) + p1.Y;
        //        y2 = k * (x2 - p1.X) + p1.Y;
        //        return new Vector2[] { new Vector2(x1, y1), new Vector2(x2, y2) };
        //    }
        //    else
        //    {
        //        x1 = -b / (2 * a);
        //        y1 = k * (x1 - p1.X) + p1.Y;
        //        Vector2 lc1 = new Vector2(x1, y1);
        //        //返回两个相同值的原因：调用时可以不管直线与圆有几个交点，只管取x轴值最大（小）的那个点。
        //        //需要判断是不是两个相同点，需自行判断两点的坐标。
        //        return new Vector2[] { lc1, lc1 };
        //    }

        //}
        /// <summary>
        /// 求圆弧与直线的交点,数组第一个点是X方向或Y方向值较小的点,直线斜率大于tan(89.99°)时视为垂直x轴的直线
        /// </summary>
        /// <param name="arc"></param>
        /// <param name="p1"></param>
        /// <param name="p2"></param>
        /// <returns></returns>
        public static Vector2[] LineXCir(Arc arc, Vector2 p1, Vector2 p2) {
            double x1 = 0;
            double x2 = 0;
            double y1 = 0;
            double y2 = 0;
            double h = arc.Center.X;
            double v = arc.Center.Y;
            double radius = arc.Radius;
            double k = 0;
            //控制斜率
            if (p1.X != p2.X)
            {
                k = (p1.Y - p2.Y) / (p1.X - p2.X);
                if (k > Math.Tan(pi / 180 * 89.99)|| k < Math.Tan(-pi / 180 * 89.99))
                    p1.X = p2.X;
            } 
            //控制斜率
            //斜率不存在x=x1或者x=x2
            if (p1.X == p2.X)
            {
                x1 = x2 = p1.X;
                double t = radius * radius - (x1 - h) * (x1 - h);
                if (t < 0)
                    return null;
                else if (t > 0)
                {
                    y1 = v - Math.Sqrt(t);
                    y2 = v + Math.Sqrt(t);
                    return new Vector2[] { new Vector2(x1, y1), new Vector2(x1, y2) };
                }
                else
                    return new Vector2[] { new Vector2(x1, v) };
            }
            //斜率存在y=kx+b;
            else
            {
                //斜率
                double b = p1.Y - k * p1.X;
                double A = 1 + k * k;
                double B = 2 * k * (b - v) - 2 * h;
                double C = h * h + (b - v) * (b - v) - radius * radius;
                double delta = B * B - 4 * A * C;
                if (delta < 0)
                    return null;
                else if (delta > 0)
                {
                    x1 = (-B - Math.Sqrt(delta)) / (2 * A);
                    y1 = k * x1 + b;
                    x2 = (-B + Math.Sqrt(delta)) / (2 * A);
                    y2 = k * x2 + b;
                    return new Vector2[] { new Vector2(x1, y1), new Vector2(x2, y2) };
                }
                else
                {
                    x1 = -B / (2 * A);
                    y1 = k * x1 + b;
                    return new Vector2[] { new Vector2(x1, y1) };
                }
                    
            }
                

        }
        //圆弧与直线的交点
        //public static List<Vector2> LineXArc(Arc arc, Vector2 p1, Vector2 p2)
        //{
        //    double pi = Math.PI;
        //    Vector2[] results = LineXCir(arc, p1, p2);
        //    if (results == null)
        //        return null;
        //    double cx = arc.Center.X;
        //    double cy = arc.Center.Y;
        //    Vector2 center = new Vector2(cx, cy);
        //    double r = arc.Radius;
        //    List<Vector2> xpoints = new List<Vector2>();
        //    double startAgl = arc.StartAngle * pi / 180;//返回角度变弧度
        //    Vector2 startPoint = fun.Polar(center, startAgl, r);
        //    double endAgl = arc.EndAngle * pi / 180;//返回角度变弧度
        //    Vector2 endPoint = fun.Polar(center, endAgl, r);
        //    //由于返回的角度在0-360度之间，或者说在0-2*pi之间，可能存在归零的情况
        //    //即起点在0点之前，结束点在0点之后，起点270度，结束点270+91度，结束点会变成1度。
        //    double theAgl = ThreePointsAngle(startPoint, center, endPoint);
        //    if (startAgl + theAgl >= 2 * pi)
        //        endAgl = startAgl + theAgl;
        //    for (int i = 0; i < 2; i++)
        //    {
        //        double agl = Vector2.Angle(center, results[i]);
        //        Console.WriteLine("agl：" + agl);
        //        if (agl >= startAgl && agl <= endAgl)
        //            xpoints.Add(results[i]);
        //    }
        //    //由于linexcir的返回结果未考虑两个交点是否是同一个点：
        //    //上诉判断过程结束后，若依然有两个点满足条件，需要判断这两个点是否是同一个点，若是，则删除集合中第二个
        //    if (xpoints.Count == 2)
        //    {
        //        if (xpoints[0].X == xpoints[1].X && xpoints[0].Y == xpoints[1].Y)
        //            xpoints.Remove(xpoints[1]);
        //    }
        //    return xpoints;
        //}
        public static List<Vector2> LineXArc(Arc arc, Vector2 p1, Vector2 p2) {
            Vector2[] results = LineXCir(arc, p1, p2);
            if (results == null)
                return null;
            //将数组中的所有交点添加到集合中，方便管理(增删)
            List<Vector2> points = new List<Vector2>();
            //圆弧的圆心
            double ax = arc.Center.X;
            double ay = arc.Center.Y;
            Vector2 center = new Vector2(ax, ay);
            //圆弧起始角度转换成弧度
            double arcStartR = arc.StartAngle * pi / 180;
            double arcEndR = arc.EndAngle * pi / 180;
            if (arcStartR == arcEndR)
                throw new Exception("圆弧起始角度与结束角度相等");
            //判断交点是否在圆弧上,简单情况,圆弧起始角小于结束角
            double testAgl = 0;
            if (arcStartR < arcEndR)
            {
                foreach (Vector2 point in results)
                {
                    testAgl = Vector2.Angle(center, point);
                    if (testAgl >= arcStartR && testAgl <= arcEndR)
                        points.Add(point);

                }
            }
            //圆弧起始角大于结束角
            else
            {
                foreach (Vector2 point in results)
                {
                    testAgl = Vector2.Angle(center, point);
                    if (testAgl >= arcStartR || testAgl <= arcEndR)
                        points.Add(point);
                }
            }
            return points;
        }
        #region 添加点到多段线方法
        //该方法将重复的添加多段线的点的过程封装，参数：多段线中点的数组或多个Vector2点，返回值：多段线。
        //仅适用于线段组成的多段线。
        public static LwPolyline AddPointsToLwPolyLine(params Vector2[] points)//多段线
        {
            LwPolyline hPline = new LwPolyline();
            for (int i = 0; i < points.Length; i++)
            {
                if (points[i].X.Equals(double.NaN) || points[i].Y.Equals(double.NaN))
                {
                    throw new Exception("第" + i + "点为非数字值");
                }
                if (points[i] == null)
                {
                    throw new Exception("第" + i + "点为空");
                }
                LwPolylineVertex point = new LwPolylineVertex(points[i]);
                hPline.Vertexes.Add(point);
            }
            return hPline;
        }
        public static LwPolyline AddPointsToLwPolyLine(List<Vector2> points)
        {
            int num = points.Count;
            Vector2[] vector2s = new Vector2[num];
            for (int i = 0; i < num; i++)
            {
                vector2s[i] = points[i];
            }
            return AddPointsToLwPolyLine(vector2s);
        }
        public static LwPolyline AddPointsToLwPolyLine(params Vector3[] points)
        {
            int num = points.Length;
            Vector2[] vector2s = new Vector2[num];
            for (int i = 0; i < num; i++)
            {
                if (points[i].Z.Equals(double.NaN))
                {
                    throw new Exception("第" + i + "点为非数字值");
                }
                if (points[i] == null)
                {
                    throw new Exception("第" + i + "点为空");
                }
                vector2s[i] = new Vector2(points[i].X, points[i].Y);
            }
            return AddPointsToLwPolyLine(vector2s);
        }

        //该方法只负责将点添加到曲线，不负责绘制非线段部分
        public static LwPolyline AddPointsToLwPolyLine(LwPolyline thePline, params Vector2[] points)
        {
            foreach (Vector2 point in points)
            {
                if (point.X.Equals(double.NaN) || point.Y.Equals(double.NaN))
                    throw new Exception("不接受浮点非数字值");
                thePline.Vertexes.Add(new LwPolylineVertex(point));
            }
            return thePline;
        }
        public static LwPolyline AddPointsToLwPolyLine(LwPolyline thePline, params Vector3[] points)
        {
            foreach (Vector3 point in points)
            {
                if (point.X.Equals(double.NaN) || point.Y.Equals(double.NaN))
                    throw new Exception("不接受浮点非数字值");
                thePline.Vertexes.Add(new LwPolylineVertex(point.X, point.Y));
            }
            return thePline;
        }
        public static LwPolyline AddPointsToLwPolyLine(Vector2 v2, Vector3 v3)
        {
            return AddPointsToLwPolyLine(v2, new Vector2(v3.X,v3.Y));
        }
        #endregion
        //截取多段线的某一段上的点(折线)
        public static LwPolyline SubPline(LwPolyline thePline, int startIndex, int endIndex)
        {
            if (startIndex < 0)
                throw new Exception("起始点脚标不能小于零");
            if (startIndex >= endIndex)
                throw new Exception("按正确顺序截取折线");
            int theNum = thePline.Vertexes.Count;
            if (endIndex >= theNum)
                throw new Exception("脚标超出目标范围");
            LwPolyline oPline = new LwPolyline();
            List<LwPolylineVertex> vertexes = thePline.Vertexes;
            for (int i = startIndex; i <= endIndex; i++)
            {
                oPline.Vertexes.Add(vertexes[i]);
            }
            return oPline;
        }
        //两点画线段，主要用于画竖直线
        public static void DrawPlineByTwoPoints(DxfDocument dxf, Vector2 point1, Vector2 point2)
        {
            Vector2[] line = { point1, point2 };
            double width = 0.1;
            Layer layer = new Layer("contour") { Color = AciColor.Cyan };    //轮廓层
            fun.drawPlineOfw(dxf, line, width, layer);
        }
        public static void DrawPlineByTwoPoints(DxfDocument dxf, Vector2 point1, Vector2 point2, Layer layer)
        {
            Vector2[] line = { point1, point2 };
            double width = 0.1;
            fun.drawPlineOfw(dxf, line, width, layer);
        }
        //该方法用于计算上下切除点与中线的高度差，参数：缝隙宽度，中线所在圆的半径，缝隙中线在zy面与z轴的夹角
        //返回x0，较小值，上。x1，较大值，下。纬度较高的对应h较小.详见gap.SLDPRT文件
        public static double[] GetH(double gap, double r, double alpha)
        {
            if (alpha == 0)
                throw new Exception("角度为零时高度为gap/2");
            double r_sagitta = Math.Sqrt(Math.Pow(r, 2) - Math.Pow(gap / 2, 2));
            double sagitta = r - r_sagitta;
            double littleBow = Math.Sqrt(Math.Pow(sagitta, 2) + Math.Pow(gap / 2, 2));
            double a = 1 + 1 / Math.Pow(Math.Tan(alpha), 2);
            double b = -gap * Math.Cos(alpha) / Math.Pow(Math.Sin(alpha), 2);
            double c = Math.Pow(gap / Math.Sin(alpha), 2) / 4 - Math.Pow(littleBow, 2);
            double x0 = (-b - Math.Sqrt(Math.Pow(b, 2) - 4 * a * c)) / (2 * a);
            double x1 = (-b + Math.Sqrt(Math.Pow(b, 2) - 4 * a * c)) / (2 * a);
            return new double[] { x0, x1 };
        }
        //斜面上切除点的高度,第一个在下，第二个在上。详见gap1.SLDPRT
        public static double[] GetHofP(double gap, double dis, double alpha)
        {
            double[] height = new double[2];
            height[0] = (dis / Math.Tan(alpha) - gap / 2) * Math.Sin(alpha);
            height[1] = (dis / Math.Tan(alpha) + gap / 2) * Math.Sin(alpha);
            return height;
        }
        //绘制多段线的镜像线
        public static LwPolyline MirrorPolyline(LwPolyline lwPolyline, Vector2 startpoint, Vector2 endpoint2)
        {
            List<LwPolylineVertex> points = lwPolyline.Vertexes;
            int num = points.Count;
            Vector2[] mpoints = new Vector2[num];
            for (int i = 0; i < num; i++)
            {
                Vector2 position = points[i].Position;
                mpoints[i] = fun.mirrorpoint(position, startpoint, endpoint2);
                    //new Vector2(position.X, 2 * startpoint.Y - position.Y);
            }
            LwPolyline mPline = AddPointsToLwPolyLine(mpoints);
            return mPline;
        }
        //绘制多段线的线
        public static Line Mirrorline(Line line, Vector2 startpoint, Vector2 endpoint2)
        {
            var v1 = new Vector2(line.StartPoint.X, line.StartPoint.Y);
            var v2 = new Vector2(line.EndPoint.X, line.EndPoint.Y);

            var m1 = fun.mirrorpoint(v1, startpoint, endpoint2);
            var m2 = fun.mirrorpoint(v2, startpoint, endpoint2);

            var line1 = new Line(m1, m2);
            return line1;
        }
        #region 填充线方法
        /// <summary>
        /// 填充路径所框起来的区域，填充的区域是一个整体,！！！在网页上无法显示填充实体！！！
        /// </summary>
        /// <param name="dxf"></param>
        /// <param name="paths"></param>
        /// <param name="angle"></param>
        /// <param name="scale"></param>
        public static void HatchByPath(DxfDocument dxf,double angle,double scale,List<EntityObject> paths)
        {
            List<HatchBoundaryPath> boundary = new List<HatchBoundaryPath>();
                boundary.Add(new HatchBoundaryPath(paths));
                Hatch hatch = new Hatch(HatchPattern.Line, boundary, true);
                hatch.Pattern.Angle = angle;
                hatch.Pattern.Scale = scale;
                hatch.Layer = new Layer("hatching") { Color = AciColor.Blue };
                dxf.AddEntity(hatch);
        }
        /// <summary>
        /// 返回填充实体
        /// </summary>
        /// <param name="paths"></param>
        /// <param name="angle"></param>
        /// <param name="scale"></param>
        /// <returns></returns>
        public static Hatch HatchByPath(List<EntityObject> paths,double angle,double scale)
        {
            List<HatchBoundaryPath> boundary = new List<HatchBoundaryPath>();
            boundary.Add(new HatchBoundaryPath(paths));
            Console.WriteLine("paths123", paths.ToString());
            Console.WriteLine("boundary123",boundary.ToString());
            Hatch hatch = new Hatch(HatchPattern.Line, boundary, true);
            hatch.Pattern.Angle = angle;
            hatch.Pattern.Scale = scale;
            hatch.Layer = new Layer("hatching") { Color = AciColor.Blue };
            return hatch;

        }
        public static void HatchByPath(DxfDocument dxf, List<EntityObject> paths) {
            HatchByPath(dxf, 45, 8,paths);
        }
        //添加剖面线,封闭曲线,仅支持直线与圆弧
        
        public static void HatchThePolyline(DxfDocument dxf, LwPolyline polyline, double pmxAngleDegree, double pmxdist)
        {
            if (!polyline.IsClosed)
                throw new Exception("非封闭曲线");
            if (pmxdist <= 0)
                throw new Exception("填充线间距错误");
            Layer hatching = new Layer("hatching") { Color = AciColor.Blue };    //填充层
            List<EntityObject> curves = polyline.Explode();
            int num = curves.Count;
            string[] typeName = new string[num];
            Line[] lines = new Line[num];
            Arc[] arcs = new Arc[num];
            for (int i = 0; i < num; i++)
            {
                typeName[i] = curves[i].Type.ToString();
                if (typeName[i] == "Line")
                {
                    lines[i] = (Line)curves[i];
                }
                else if (typeName[i] == "Arc")
                {
                    arcs[i] = (Arc)curves[i];
                }
            }
            fun.hatchsuboflineandarc(dxf, typeName, num, pmxAngleDegree, pmxdist, lines, arcs, hatching);
        }
        public static void HatchThePolyline(DxfDocument dxf, LwPolyline polyline)
        {
            HatchThePolyline(dxf, polyline, 45, 5);
        }
        #endregion
    }
}
